from math import exp
from math import sqrt
import sys
from KQueensSA import KQueensSA
from KQueensMC import KQueensMC
from GraphColorSA import GraphColorSA
from GraphColorMC import GraphColorMC

def main():
	
	print "Welcome to the GPS by Valerio Amodeo e Marc Baro!"
	print "Select the type of problem you wish to solve:\n1 - K-Queens (SA)\n2 - K-Queens (MC)\n3 - Graph Color (SA)\n4 - Graph Color (MC)\n5 - Sudoku (SA - Only Easy)\n6 - Sudoku (MC)"
	while True:
		try:
			number = int (raw_input('Type a number: '))
			if number > 6 or number < 1:
				raise ValueError
			break
		except ValueError:
			print "Invalid input - Not a number or wrong value"
	print "Select the level of difficulty:\n1 - Easy\n2 - Medium\n3 - Hard"
	while True:
		try:
			difficulty = int (raw_input('Type a number: '))
			if difficulty > 3 or difficulty < 1:
				raise ValueError
			break
		except ValueError:
			print "Invalid input - Not a number or wrong value"
	print "Select the mode:\n1 - Normal\n2 - Test"
	while True:
		try:
			mode = int (raw_input('Type a number: '))
			if mode > 2 or mode < 1:
				raise ValueError
			break
		except ValueError:
			print "Invalid input - Not a number or wrong value"
	if mode == 2:
		print "How many runs?"
		while True:
			try:
				runs = int (raw_input('Type a number: '))
				if runs < 1 :
					raise ValueError
				break
			except ValueError:
				print "Invalid input - Not a number or wrong value"
	if number == 1:
		if mode == 1:
			simulatedAnneling = KQueensSA(difficulty)
			result = simulatedAnneling.simulateAnneling()
		elif mode == 2:
			result = []
			for i in range(runs):
				simulatedAnneling = KQueensSA(difficulty)
				result += [simulatedAnneling.simulateAnneling()]
	elif number == 2:
		if mode==1:
			minConflicts = KQueensMC(difficulty)
			result = minConflicts.minConflicts()
		elif mode == 2:
			result = []
			for i in range(runs):
				minConflicts = KQueensMC(difficulty)
				result += [minConflicts.minConflicts()]
	elif number == 3:
		if mode == 1:
			simulatedAnneling = GraphColorSA(difficulty)
			result = simulatedAnneling.simulateAnneling()
		elif mode == 2:
			result = []
			for i in range(runs):
				simulatedAnneling = GraphColorSA(difficulty)
				result += [simulatedAnneling.simulateAnneling()]
	elif number == 4:
		if mode == 1:
			minConflicts = GraphColorMC(difficulty)
			result = minConflicts.minConflicts()
		elif mode == 2:
			result = []
			for i in range(runs):
				minConflicts = GraphColorMC(difficulty)
				result += [minConflicts.minConflicts()]
	elif number == 5:
		if mode ==1:
			simulatedAnneling = SudokuSA(difficulty)
			result = simulatedAnneling.simulatedAnneling()
		elif mode ==2:
			result = []
			for i in range(runs):
				simulatedAnneling = SudokuSA(difficulty)
				result += [simulatedAnneling.simulatedAnneling()]
	elif number == 6:
		if mode==1:
			minConflicts = SudokuMC(difficulty)
			result = minConflicts.minConflicts()
		elif mode == 2:
			result = []
			for i in range(runs):
				minConflicts = SudokuMC(difficulty)
				result += [minConflicts.minConflicts()]
	if mode == 1:
		print "The result is :\nState:\t" + str(result[0]) + "\nCycles:\t" + str(result[1]) + "\nConflicts:\t" + str(result[2]) 
	elif mode == 2:
		print "Test results\n----------------------------------------------------------\nNumber of tests:\t\t" + str(len(result))
		averageConflicts = 0
		standardDevConflicts = 0
		averageDevConflicts = 0
		bestEvalutation = sys.maxint
		averageSteps = 0
		standardDevSteps = 0
		averageDevSteps = 0
		bestStep = sys.maxint
		bestState = None
		for i in result:
			averageConflicts += i[2]
			averageSteps += i[1]
			if i[2]<bestEvalutation:
				bestEvalutation=i[2]
			if i[1] < bestStep:
				bestStep = i[1]
		averageConflicts = averageConflicts/len(result)
		averageSteps = averageSteps/len(result)
		print "Average Conflicts:\t\t" + str(averageConflicts)
		for i in result:
			standardDevConflicts += (i[2]-averageConflicts)**2
			standardDevSteps += (i[1]-averageSteps)**2
			if i[2] == bestEvalutation:
				bestState = i[0]
			averageDevConflicts += abs(i[2]-averageConflicts)
		averageDevConflicts = averageDevConflicts/len(result)
		standardDevConflicts = sqrt(standardDevConflicts/len(result))
		averageDevSteps = averageDevConflicts/len(result)
		standardDevSteps = sqrt(standardDevSteps/len(result))
		print "Standard Deviation Conflicts:\t" + str(standardDevConflicts) + "\nAverage Deviation Conflicts:\t" + str(averageDevConflicts) + "\nBest Evalutation:\t\t" + str(bestEvalutation) + "\nBest State:\t\t\t" + str(bestState) + "\n----------------------------------------------------------"
		print "Standard Deviation Steps:\t" + str(standardDevSteps) + "\nAverage Deviation Steps:\t" + str(averageDevSteps) + "\nBest Steps:\t\t\t" + str(bestStep) + "\n----------------------------------------------------------"
if __name__ == "__main__":
    main()